﻿using Architecture.CrossCutting.Common;
using Architecture.CrossCutting.Common.Logging;
using Architecture.CrossCutting.Web.Tracing;
using Architecture.CrossCutting.Web.Tracing.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Tracing;
using System.Threading;

namespace Architecture.CrossCutting.Web.WebApi
{
    /// <summary>
    /// Implementation of <see cref="ITraceWriter"/> that traces to ETW.
    /// </summary>
    public class WebApiDiagnostic : DelegatingHandler
    {

        IGenericLogger<WebApiLog> _logger;

        /// <summary>
        /// Instantiates an instance of the <see cref="WebApiEtwTraceWriter"/> class.
        /// </summary>
        public WebApiDiagnostic(IGenericLogger<WebApiLog> logger)
        {
            _logger = logger;
        }


        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {

            //Create WebApiLog
            var log = new WebApiLog()
            {
                Application = "Unknown",
            };

            log.RegisterRequest(request);
            log.SetStartRequestSent();

            //_logger.WriteInfo("Begin Test WebApiLog", log);
            System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
            watch.Start();

            var taskScheduler = TaskScheduler.Default;
            if (System.Web.HttpContext.Current != null)
            {
                taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
            }

            return await base.SendAsync(request, cancellationToken)
                .ContinueWith(task =>
                {
                    var response = task.Result;
                    watch.Stop();

                    log.RegisterResponse(response);
                    log.UpdateExecutionContext();
                    log.SetResponseReceived(watch.ElapsedMilliseconds);


                    switch (task.Status)
                    {
                        case TaskStatus.RanToCompletion:
                            {
                                _logger.WriteInfo("End Test WebApiLog", log);
                                break;
                            }
                        case TaskStatus.Faulted:
                            {
                                _logger.WriteError("End Test WebApiLog", log, task.Exception);
                                break;
                            }
                    }
                    return response;
                }, cancellationToken, TaskContinuationOptions.AttachedToParent, taskScheduler);

        }


    }
}
